package juc.utils.locks;

import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

public class ReentrantLockExample {
    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        /*IntStream.range(0, 2).forEach(i -> new Thread() {
            @Override
            public void run() {
                needLock();
                //needLockBySync();
            }
        }.start());*/

        Thread t1 = new Thread() {
            @Override
            public void run() {
                testUnInterruptibly();
                //testTryLock();
            }
        };
        t1.start();
        TimeUnit.SECONDS.sleep(1);
        Thread t2 = new Thread() {
            @Override
            public void run() {
                testUnInterruptibly();
                //testTryLock();
            }
        };
        t2.start();
        TimeUnit.SECONDS.sleep(1);
        //t2.interrupt();
        Optional.of(lock.getQueueLength()).ifPresent(System.out::println);
        Optional.of(lock.hasQueuedThreads()).ifPresent(System.out::println);
        Optional.of(lock.hasQueuedThread(t1)).ifPresent(System.out::println);
        Optional.of(lock.hasQueuedThread(t2)).ifPresent(System.out::println);
        //是否被其他线程held
        Optional.of(lock.isLocked()).ifPresent(System.out::println);

        System.out.println("===");
    }

    public static void testTryLock() {
        //尝试取锁
        if (lock.tryLock()) {
            try {
                Optional.of("The thread-" + Thread.currentThread().getName() + " get lock and will do working").ifPresent(System.out::println);
                while (true) {

                }
            } finally {
                lock.unlock();
            }
        } else {
            Optional.of("The thread-" + Thread.currentThread().getName() + " not get lock").ifPresent(System.out::println);
        }
    }

    public static void testUnInterruptibly() {
        try {
            //允许被中断
            lock.lockInterruptibly();
            //getHoldCount当前线程获取的锁数量
            Optional.of(Thread.currentThread().getName() +"~ "+ lock.getHoldCount()).ifPresent(System.out::println);
            Optional.of("The thread-" + Thread.currentThread().getName() + " get lock and will do working").ifPresent(System.out::println);
            while (true) {

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void needLock() {
        try {
            lock.lock();
            Optional.of("The thread-" + Thread.currentThread().getName() + " get lock and will do working").ifPresent(System.out::println);
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void needLockBySync() {
        synchronized (ReentrantLockExample.class) {
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
